package com.hejia.alauda.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hejia.alauda.entity.*;
import com.hejia.alauda.entity.example.BankInfoExample;
import com.hejia.alauda.entity.example.BankMaintainExample;
import com.hejia.alauda.entity.example.PayGateExample;
import com.hejia.alauda.exception.BusinessException;
import com.hejia.alauda.utils.Pager;
import com.yeepay.yjpay.service.PayAPIService;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Created by Johnny(johnny@hejiajinrong.com) on 15/3/3.
 */

@Service
public interface PaymentService {

	// PAY-支付，REFUND-退款，QUERY-查询
	public enum UPOP_Action {
		PAY, REFUND, QUERY
	}

	// PAY-支付，QUERY-查询，WHITELIST-白名单提交
	public enum SFJ_Action {
		PAY, QUERY, WHITELIST
	}

	/**
	 * 增加银行
	 *
	 * @param payGateBank
	 * @return
	 */
	boolean addPayGateBank(PayGateBank payGateBank);

	/**
	 * 删除银行
	 *
	 * @param payGateBank
	 * @return
	 */
	boolean deletePayGateBank(PayGateBank payGateBank);

	/**
	 * 删除银行根据paygateid
	 *
	 * @param payGateBank
	 * @return
	 */
	boolean deletePayGateBankByPid(Long id);

	/**
	 * 查找银行
	 *
	 * @param id
	 * @return
	 */
	PayGateBank findPayGateBankById(Long id);

	/**
	 * 修改银行
	 *
	 * @param payGateBank
	 * @return
	 */
	boolean modifyPayGateBank(PayGateBank payGateBank);

	/**
	 * 根据支付网关ID获取银行列表
	 *
	 * @param payGateId
	 * @return
	 */
	public List<PayGateBank> getPayGateBankByPayGateId(Long payGateId);

	/**
	 * 根据支付网关ID和银行编码查询支付网关银行
	 *
	 * @param payGateId
	 * @param bankcode
	 * @return
	 */
	public PayGateBank getPayGateBankByPayGateIdAndBankcode(Long payGateId,
			String bankcode);

	/**
	 * 查询所有支付网关
	 *
	 * @param pager
	 * @return
	 */
	public Pager<PayGate> findAllPayGate(Pager<PayGate> pager);

	/**
	 * 查询所有支付网关
	 *
	 * @param pager
	 * @param example
	 * @return
	 */
	public Pager<PayGate> findAllPayGate(Pager<PayGate> pager,
			PayGateExample example);

	/**
	 * 保存支付网关
	 *
	 * @param payGate
	 * @return
	 */
	public boolean savePayGate(PayGate payGate);

	/**
	 * 根据ID获取支付网关
	 *
	 * @param id
	 * @return
	 */
	public PayGate getPayGateById(Long id);

	/**
	 * 修改支付网关
	 *
	 * @param payGate
	 * @return
	 */
	public boolean modifyPayGate(PayGate payGate);

	/**
	 * 删除支付网关
	 *
	 * @param id
	 * @return
	 */
	public boolean deletePayGate(Long id);

	/**
	 * 查询所有支付网关
	 *
	 * @return
	 */
	public List<PayGate> getPayGateList();

	/**
	 * 保存支付通知日志
	 *
	 * @param log
	 *            支付通知日志
	 * @return
	 */
	public boolean savePayNotifyLog(PayNotifyLog log);


	/**
	 * 是否存在
	 * 
	 * @param cardNumber
	 * @return true - 存在，false - 不存在
	 */
	boolean isExist(String cardNumber);

	/**
	 * 变更银行卡
	 * 
	 * @param originalBankCardId 	银行卡ID
	 * @param newBankCardId 银行卡号
	 * @throws com.hejia.alauda.exception.BusinessException
	 */
	void changeBankCard(Long originalBankCardId, Long newBankCardId) throws BusinessException;

	boolean modifyBankCard(BankCard bankCard);
	/**
	 * 查找银行卡列表
	 * 
	 * @param userId
	 * @return
	 */
	List<BankCard> findBankCardsByUserId(Long userId);

	/**
	 * 解绑连连支付
	 * 
	 * @param bankCardId
	 *            银行卡ID
	 * @throws BusinessException
	 */
	void unbindLLPay(Long bankCardId) throws BusinessException;

	/**
	 * 修改银行信息
	 *
	 * @param bankInfo
	 * @return
	 */
	boolean modifyBankInfo(BankInfo bankInfo);

	/**
	 * 根据ID获取银行信息
	 *
	 * @param id
	 * @return
	 */
	BankInfo getBankInfoById(Long id);

	/**
	 * 根据银行编码获取银行信息
	 *
	 * @param bankCode
	 * @return
	 */
	BankInfo getBankInfoByBankCode(String bankCode);

	/**
	 * 获取所有银行信息
	 *
	 * @return
	 */

	public List<BankInfo> findAllBankInfo();

	/**
	 * 查询所有银行
	 *
	 * @param pager
	 * @return
	 */
	public Pager<BankInfo> findAllBankInfo(Pager<BankInfo> pager);

	/**
	 * 查询所有银行
	 *
	 * @param pager
	 * @param example
	 * @return
	 */
	public Pager<BankInfo> findAllBankInfo(BankInfoExample example,
			Pager<BankInfo> pager);

	/**
	 * 保存银行
	 *
	 * @param bankInfo
	 * @return
	 */
	public boolean saveBankInfo(BankInfo bankInfo);

	/**
	 * 删除银行
	 *
	 * @param id
	 * @return
	 */
	public boolean deleteBankInfo(Long id);

	/**
	 * 修改银行
	 *
	 * @param bankInfo
	 * @return
	 */
	public boolean updateBankInfo(BankInfo bankInfo);

	/**
	 * 绑定银行卡
	 * 
	 * @param bankcard
	 * @return
	 */
	boolean saveBankCard(BankCard bankcard);

	/**
	 * 根据用户来查找绑定过的银行卡的列表
	 * 
	 * @param user
	 * @return
	 */
	List<BankCard> findBankCardByUser(User user);

	/**
	 * 根据用户查找所有银行卡，包括未绑定过的银行卡
	 * 
	 * @param user
	 * @return
	 */
	List<BankCard> findAllBankCardByUser(User user);

	/**
	 * 根据ID获得银行卡信息
	 * 
	 * @param id
	 * @param delay
	 */
	BankCard findBankCardById(Long id);

	/**
	 * 根据银行卡号查询银行卡信息
	 * 
	 * @param cardNumber
	 * @return
	 */
	BankCard findBankCardByCardNumber(String cardNumber, Long id);

	/**
	 * 当连连支付异步回调的时候要把结果放在redis中
	 * 
	 * @param isSuccess
	 */
	void setFinalPayStatus(String orderNumber, boolean isSuccess);

	/**
	 * 在redis中确认订单是否真的支付成功
	 * 
	 * @param orderNumber
	 * @return
	 */
	Boolean getFinalPayStatus(String orderNumber);

	/**
	 * 实际支付的业务接口
	 * 
	 * @param id
	 * @return
	 */
	boolean payOrder(Order order, boolean devMode);


	/**
	 * 更新订单支付信息
	 * 
	 * @param id
	 *            订单号
	 * @param payNumber
	 *            支付订单号
	 * @param bankcard
	 *            支付银行卡
	 * @param status
	 *            订单状态
	 * @return
	 */
	boolean updatePayInfo(Long id, String payNumber, BankCard bankcard,
			Order.Status status);

	/**
	 * 银行维护列表
	 * 
	 * @param pager
	 * @return
	 */
	public Pager<BankMaintain> findAllBankMaintain(Pager<BankMaintain> pager);

	/**
	 * 银行维护列表
	 * 
	 * @param pager
	 * @param example
	 * @return
	 */
	public Pager<BankMaintain> findAllBankMaintain(Pager<BankMaintain> pager,
			BankMaintainExample example);

	/**
	 * 保存银行维护
	 *
	 * @param BankMaintain
	 * @return
	 */
	public boolean saveBankMaintain(BankMaintain bankMaintain);

	/**
	 * 根据ID获取银行维护
	 *
	 * @param id
	 * @return
	 */
	public BankMaintain getBankMaintainById(Long id);

	/**
	 * 修改银行维护
	 *
	 * @param BankMaintain
	 * @return
	 */
	public boolean updateBankMaintain(BankMaintain bankMaintain);

	/**
	 * 删除银行维护
	 *
	 * @param id
	 * @return
	 */
	public boolean deleteBankMaintain(Long id);

	/**
	 * 查询该银行是否维护中
	 * 
	 * @param bankCode
	 * @return
	 */
	public boolean isBankMaintain(String bankCode);

	/**
	 * 查询用户已绑定的银行卡
	 * @param userId	用户ID
	 * @return	用户已绑定的银行卡
	 */
	List<BankCard> findBindedBankCardsByUserId(Long userId);

	/**
	 * 解绑银行卡
	 * @param bankCardId	银行卡ID
	 * @throws BusinessException 
	 */
	void unbindBankCard(Long bankCardId) throws BusinessException;

	/**
	 * 查找银行卡
	 * @param keyword	关键词
	 * @param pager		页
	 * @return	银行卡列表
	 */
	Pager<BankCard> findBankCardsByKeyword(String keyword, Pager<BankCard> pager);

	/**
	 * 保存支付通知日志
	 * @param payGate	支付网关
	 * @param type		通知类型
	 * @param content	通知内容
	 */
	void savePayNotifyLog(String payGate, String type, String content);

	/**
	 * 获取银行卡支付网关单日支付超限金额
	 * @param bankCard		银行卡
	 * @param payGateBank	支付网关银行
	 * @param amount 购买金额
	 * @return	单日支付超限金额
	 */
	Long getBankCardDayExceedAmount(BankCard bankCard, PayGateBank payGateBank, Long amount);

	/**
	 * 获取银行卡支付网关单月支付超限金额
	 * @param bankCard		银行卡
	 * @param payGateBank	支付网关银行
	 * @param amount 购买金额
	 * @return	单月支付超限金额
	 */
	Long getBankCardMonthExceedAmount(BankCard bankCard, PayGateBank payGateBank, Long amount);

	/**
	 * 订单支付通知是否已经处理
	 * @param order 订单
	 * @return
	 */
	boolean isPayNotifyHandled(Order order);

	/**
	 * 订单支付成功通知处理
	 * @param order 订单
	 * @param devMode 是否开发模式
	 * @return true - 处理完订单支付成功通知，false - 未处理订单支付成功通知
	 */
	boolean payNotifySuccess(Order order, boolean devMode);

	/**
	 * 订单支付失败通知处理
	 * @param order
	 */
	void payNotifyFailure(Order order);
	
	/**
	 * 根据还款订单号获取还款订单
	 * @param	orderNumber
	 * @return	还款订单
	 */
	RepaymentOrder findRepaymentOrderByOrderNumber(String orderNumber);

	/**
	 * 还款通知成功处理
	 * @param executor 
	 * @param orderNumber 订单号
	 */
	void repayNotifySuccess(Executor executor, String orderNumber);
	
	/**
	 * 还款通知失败处理
	 * @param orderNumber 订单号
	 */
	void repayNotifyFailure(String orderNumber);
	
	/**
	 * 申请红包打款
	 * 同个用户一天内申请，同类红包以一笔打款打给用户
	 * @param bonusOrderId 红包订单ID
	 */
	void applyBonusRepay(Long bonusOrderId);

	/**
	 * 同步订单支付状态
	 * @param orderId 订单ID
	 * @param payGateStatus 支付网关支付状态
	 */
	void updateOrderPayGateStatus(Long orderId, String payGateStatus);

	/**
	 * 同步连连支付银行状态和限额
	 * 
	 * @param bankList 银行列表
	 */
	void syncLLPayBankStatusAndLimit(JSONArray bankList);

	/**
	 * 解绑易宝支付
	 * @param payAPIService
	 * @param bankCard
	 * @throws Exception 
	 */
	void unbindYeePay(PayAPIService payAPIService, BankCard bankCard) throws Exception;

	/**
	 * 添加支付订单
	 * @param payOrder	支付订单
	 */
	void addPayOrder(PayOrder payOrder);

	/**
	 * 提前兑付资产
	 * @param financingId	资产ID
	 * @param advancePaymentDate	提前兑付日期
	 */
	void advancePaymentFinancing(Long financingId, Date advancePaymentDate);
	
	/**
	 * 补充掉单的订单
	 * @param orderNumber
	 * @return
	 */
	boolean supplyOrder(String orderNumber);

	/**
	 * 根据支付网关代码查询银行
	 * 
	 * @param payGateCode
	 * @return
	 */
	List<PayGateBank> findPayGateBanksByPayGateCode(String payGateCode);
	
	/**
	 * 手动处理订单
	 * @param order
	 * @return
	 */
	boolean payOrderManual(Order order);

	/**
	 * 查询支付网关银行
	 * @param payGateId	支付网关ID
	 * @param bankCode	银行编码
	 * @return
	 */
	PayGateBank findPayGateBank(Long payGateId, String bankCode);

	/**
	 * 发送支付验证码
	 * @param mobile 手机
	 * @param order 订单
	 */
	void sendPayIdentifyingCode(String mobile, Order order);

	/**
	 * 更新银行卡预留手机号
	 * @param bankCardId	银行卡ID
	 * @param mobile 银行预留手机号
	 */
	void updateBankCardMobile(Long bankCardId, String mobile);

	/**
	 * 更新支付网关支付状态
	 * @param payNumber 支付订单号
	 * @param payGateStatus	支付网关状态
	 * @param payGateStatusDescription 支付网关状态描述
	 */
	void updateOrderPayGateStatusByPayNumber(String payNumber, String payGateStatus, String payGateStatusDescription);
	
	String checkBankCard(String payNumber, String mobile, BankCard bankcard) throws Exception;
	
	/**
	 * 
	 * @param cardNumber
	 * [0] bankCode
	 * [1] bankName
	 * @return
	 */
	String[] getBankCodeByCardNumber(String cardNumber);
}
